//
//  ProblemOffer61.swift
//  TestProject
//
//  Created by 武侠 on 2021/7/14.
//  Copyright © 2021 zhulong. All rights reserved.
//

import UIKit

/*
 剑指 Offer 61. 扑克牌中的顺子 ✅
 从扑克牌中随机抽5张牌，判断是不是一个顺子，即这5张牌是不是连续的。2～10为数字本身，A为1，J为11，Q为12，K为13，而大、小王为 0 ，可以看成任意数字。A 不能视为 14。
 示例 1:
     输入: [1,2,3,4,5]
     输出: True
 示例 2:
     输入: [0,0,1,2,5]
     输出: True
 限制：数组长度为 5
 数组的数取值为 [0, 13] .
 */
@objcMembers class ProblemOffer61: NSObject {
    func solution() {
        print(isStraightS([0,0,9,12,13]))
    }
    
    /*
     1: 创建一个z，记录0的个数
     2: 首先判断数组的第一个数：
       2.1> n==0, z++ 判断下一个
       2.2> n!=0, 创建一个数组，他的长度是：[n-4, n+4]
     */
    func isStraight(_ nums: [Int]) -> Bool {
        var z = 0
        var list = Array(repeating: -1, count: 13)
        // 遍历数组，把牌放入list中
        for n in nums {
            if n == 0 {
                z += 1
            } else {
                if list[n-1] != -1 {        // 2张相同的牌，不可能有顺子
                    return false
                } else {
                    list[n-1] = 1
                }
            }
        }
        if z >= 4 {
            return true
        }
        
        var l = 0
        var first = false       // 标识第一个数字
        for n in list {
            // 找到第一个数字
            if first == false && n == -1 {
                continue
            }
            
            if n == -1 {        // == -1 说明没有该牌，那么用z来替代
                if z > 0 {
                    z -= 1
                } else {
                    return false
                }
            }
            l += 1              // 统计牌数
            first = true
            
            if l == 5 {         // 够顺子了
                return true
            }
        }
        
        return l + z == 5       // 例如：0 0 11 12 13 的情况
    }
    
    /*
     能够成顺子，那么最大值 - 最小值 < 5
     */
    func isStraightS(_ nums: [Int]) -> Bool {
        var minV = 14
        var maxV = 1
        
        var list = Array(repeating: -1, count: 13)
        for n in nums {
            if n == 0 {
                continue
            }
            if list[n-1] != -1 {        // 出现重复牌
                return false
            } else {
                list[n-1] = 1
                minV = min(minV, n)
                maxV = max(maxV, n)
            }
        }
        return maxV - minV < 5
    }
}
